<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"yoursite.com","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"always","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="基本概念&#x3D;&#x3D;webpack 是一个现代 JavaScript 应用程序的静态模块打包器。当 webpack 处理应用程序时，它会递归地构建一个依赖关系图，其中包含应用程序需要的每个模块，然后将所有这些模块打包成一个或多个 bundle。&#x3D;&#x3D; 四个核心概念：  &#x3D;&#x3D;入口(entry)&#x3D;&#x3D; &#x3D;&#x3D;输出(output)&#x3D;&#x3D; &#x3D;&#x3D;loader&#x3D;&#x3D; &#x3D;&#x3D;插件(plugins)&#x3D;&#x3D;  入口(entry)&#x3D;&#x3D;入口">
<meta property="og:type" content="website">
<meta property="og:title" content="webpack">
<meta property="og:url" content="http://yoursite.com/webpack/index.html">
<meta property="og:site_name" content="Albert Guo">
<meta property="og:description" content="基本概念&#x3D;&#x3D;webpack 是一个现代 JavaScript 应用程序的静态模块打包器。当 webpack 处理应用程序时，它会递归地构建一个依赖关系图，其中包含应用程序需要的每个模块，然后将所有这些模块打包成一个或多个 bundle。&#x3D;&#x3D; 四个核心概念：  &#x3D;&#x3D;入口(entry)&#x3D;&#x3D; &#x3D;&#x3D;输出(output)&#x3D;&#x3D; &#x3D;&#x3D;loader&#x3D;&#x3D; &#x3D;&#x3D;插件(plugins)&#x3D;&#x3D;  入口(entry)&#x3D;&#x3D;入口">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://inews.gtimg.com/newsapp_ls/0/12134390255/0">
<meta property="article:published_time" content="2020-02-13T09:17:38.000Z">
<meta property="article:modified_time" content="2020-07-22T12:15:38.955Z">
<meta property="article:author" content="Albert Guo">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://inews.gtimg.com/newsapp_ls/0/12134390255/0">

<link rel="canonical" href="http://yoursite.com/webpack/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : false,
    lang   : 'zh-CN'
  };
</script>

  <title>webpack | Albert Guo
</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Albert Guo</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-bars fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-address-card fa-fw"></i>简介</a>

  </li>
        <li class="menu-item menu-item-webpack">

    <a href="/webpack/" rel="section"><i class="fa fa-bookmark fa-fw"></i>webpack</a>

  </li>
        <li class="menu-item menu-item-javascript">

    <a href="/JavaScript/" rel="section"><i class="fa fa-bookmark fa-fw"></i>ECMAScript 5.1</a>

  </li>
        <li class="menu-item menu-item-ecmascript6">

    <a href="/ECMAScript6/" rel="section"><i class="fa fa-bookmark fa-fw"></i>ECMAScript 6</a>

  </li>
        <li class="menu-item menu-item-react">

    <a href="/React/" rel="section"><i class="fa fa-bookmark fa-fw"></i>React</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          
  
  

          <div class="content page posts-expand">
            

    
    
    
    <div class="post-block" lang="zh-CN">
      <header class="post-header">

<h1 class="post-title" itemprop="name headline">webpack
</h1>

<div class="post-meta">
  

</div>

</header>

      
      
      
      <div class="post-body">
          <h1 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h1><p>==webpack 是一个现代 JavaScript 应用程序的静态模块打包器。当 webpack 处理应用程序时，它会递归地构建一个依赖关系图，其中包含应用程序需要的每个模块，然后将所有这些模块打包成一个或多个 <code>bundle</code>。==</p>
<p>四个核心概念：</p>
<ul>
<li>==入口(<code>entry</code>)==</li>
<li>==输出(<code>output</code>)==</li>
<li>==<code>loader</code>==</li>
<li>==插件(<code>plugins</code>)==</li>
</ul>
<h2 id="入口-entry"><a href="#入口-entry" class="headerlink" title="入口(entry)"></a>入口(entry)</h2><p>==入口起点表示 webpack 应该使用哪个模块，来作为构建其内部依赖图的开始。== 进入入口起点后，webpack 会找出有哪些模块和库是入口起点（直接和间接）依赖的。</p>
<p>每个依赖项随即被处理，最后输出到称之为 <code>bundles</code> 的文件中。</p>
<p>可以通过在 webpack 配置中配置 <code>entry</code> 属性，来指定一个入口起点（或多个入口起点）。默认值为 <code>./src</code>。</p>
<p><code>entry</code> 配置的最简单例子：</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  entry: <span class="string">'./path/to/my/entry/file.js'</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h2 id="出口-output"><a href="#出口-output" class="headerlink" title="出口(output)"></a>出口(output)</h2><p><code>output</code> 属性告诉 webpack 在哪里输出它所创建的 <code>bundles</code>，以及如何命名这些文件，默认值为 <code>./dist</code>。基本上，整个应用程序结构，都会被编译到指定的输出路径的文件夹中。可以通过在配置中指定一个 <code>output</code> 字段，来配置这些处理过程：</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  entry: <span class="string">'./path/to/my/entry/file.js'</span>,</span><br><span class="line">  output: &#123;</span><br><span class="line">    path: path.resolve(__dirname, <span class="string">'dist'</span>),</span><br><span class="line">    filename: <span class="string">'my-first-webpack.bundle.js'</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>在上面的示例中，通过 <code>output.filename</code> 和 <code>output.path</code> 属性，来告诉 <code>webpack bundle</code> 的名称，以及 <code>bundle</code> 生成的路径。上面导入的 ==path 是一个 Node.js 核心模块，用于操作文件路径。==</p>
<h2 id="loader"><a href="#loader" class="headerlink" title="loader"></a>loader</h2><p>==<code>loader</code> 让 webpack 能够去处理那些非 JavaScript 文件（webpack 自身只理解 JavaScript）。<code>loader</code> 可以将所有类型的文件转换为 webpack 能够处理的有效模块，然后利用 webpack 的打包能力，对它们进行处理。==</p>
<p>本质上，<code>webpack loader</code> 将所有类型的文件，转换为应用程序的依赖图（和最终的 <code>bundle</code>）可以直接引用的模块。</p>
<p>注意，==<code>loader</code> 能够 <code>import</code> 导入任何类型的模块（例如 <code>.css</code> 文件），这是 webpack 特有的功能，其他打包程序或任务执行器的可能并不支持。== </p>
<p>在 webpack 的配置中 <code>loader</code> 有两个属性：</p>
<ol>
<li><code>test</code> 属性：用于标识出应该被对应的 <code>loader</code> 进行转换的某个或某些文件。</li>
<li><code>use</code> 属性：表示进行转换时，应该使用哪个 <code>loader</code>。</li>
</ol>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> config = &#123;</span><br><span class="line">  output: &#123;</span><br><span class="line">    filename: <span class="string">'my-first-webpack.bundle.js'</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="built_in">module</span>: &#123;</span><br><span class="line">    rules: [</span><br><span class="line">      &#123; <span class="attr">test</span>: <span class="regexp">/\.txt$/</span>, <span class="attr">use</span>: <span class="string">'raw-loader'</span> &#125;</span><br><span class="line">    ]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = config;</span><br></pre></td></tr></table></figure>

<p>以上配置中，对一个单独的 <code>module</code> 对象定义了 <code>rules</code> 属性，里面包含两个必须属性：<code>test</code> 和 <code>use</code>。这告诉 webpack 编译器(compiler) 如下信息：</p>
<blockquote>
<p>“嘿，webpack 编译器，当你碰到「在 <code>require()/import</code> 语句中被解析为 ‘.txt’ 的路径」时，在你对它打包之前，先使用 raw-loader 转换一下。”</p>
</blockquote>
<p>==在 webpack 配置中定义 loader 时，要定义在 module.rules 中，而不是 rules。否则，会予以警告。==</p>
<h2 id="插件-plugins"><a href="#插件-plugins" class="headerlink" title="插件(plugins)"></a>插件(plugins)</h2><p><code>loader</code> 被用于转换某些类型的模块，而插件则可以用于执行范围更广的任务。</p>
<p><code>plugins</code> 可以在 webpack 运行到某个时刻的时候，做一些事情，有点类似于生命周期。</p>
<p>插件的范围包括，从打包优化和压缩，一直到重新定义环境中的变量。插件接口功能极其强大，可以用来处理各种各样的任务。</p>
<p>==想要使用一个插件，只需要 <code>require()</code> 它，然后把它添加到 <code>plugins</code> 数组中。多数插件可以通过选项(<code>option</code>)自定义。== 也可以在一个配置文件中因为不同目的而多次使用同一个插件，这时需要通过使用 <code>new</code> 操作符来创建它的一个实例。</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> HtmlWebpackPlugin = <span class="built_in">require</span>(<span class="string">'html-webpack-plugin'</span>); <span class="comment">// 通过 npm 安装</span></span><br><span class="line"><span class="keyword">const</span> webpack = <span class="built_in">require</span>(<span class="string">'webpack'</span>); <span class="comment">// 用于访问内置插件</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> config = &#123;</span><br><span class="line">  <span class="built_in">module</span>: &#123;</span><br><span class="line">    rules: [</span><br><span class="line">      &#123; <span class="attr">test</span>: <span class="regexp">/\.txt$/</span>, <span class="attr">use</span>: <span class="string">'raw-loader'</span> &#125;</span><br><span class="line">    ]</span><br><span class="line">  &#125;,</span><br><span class="line">  plugins: [</span><br><span class="line">    <span class="keyword">new</span> HtmlWebpackPlugin(&#123;<span class="attr">template</span>: <span class="string">'./src/index.html'</span>&#125;)</span><br><span class="line">  ]</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = config;</span><br></pre></td></tr></table></figure>

<p>webpack 提供许多开箱可用的插件，详情参照官网提供。</p>
<hr>
<h1 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h1><p>安装开始之前，==请确保安装了 Node.js 的最新版本。== 建议使用 Node.js 最新的长期支持版本(LTS - Long Term Support)。</p>
<h2 id="本地安装"><a href="#本地安装" class="headerlink" title="本地安装"></a>本地安装</h2><p>目前（2020/04/18）最新的webpack版本是：</p>
<p><code>webpack v4.42.1</code></p>
<p>要安装最新版本或特定版本，请运行以下命令之一：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev webpack</span><br><span class="line">npm install --save-dev webpack@&lt;version&gt;</span><br></pre></td></tr></table></figure>

<p>==如果要使用 <code>webpack 4+</code> 版本，还需要安装 <code>CLI</code>。==</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev webpack-cli</span><br></pre></td></tr></table></figure>

<h2 id="全局安装"><a href="#全局安装" class="headerlink" title="全局安装"></a>全局安装</h2><p>以下的 NPM 安装方式，将使 webpack 在全局环境下可用：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --global webpack</span><br></pre></td></tr></table></figure>

<p>==不推荐全局安装 webpack。== 这会将项目中的 webpack 锁定到指定版本，并且在使用不同的 webpack 版本的项目中，可能会导致构建失败。</p>
<hr>
<h1 id="webpack-config-js"><a href="#webpack-config-js" class="headerlink" title="webpack.config.js"></a>webpack.config.js</h1><p>在 webpack 4 中，可以无须任何配置使用。即安装完 webpack ，就可以尝试进行简单的 <code>*.js</code> 文件模块打包。但是默认提供的打包配置比较简单，无法满足日常工作项目，通常需要自行进行扩展配置。可以在项目目录下新建 <code>webpack.config.js</code> 进行编辑配置。</p>
<p><em>webpack.config.js</em></p>
<blockquote>
<p>该配置仅供参考，实际工作以实际需求配置为准。</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  mode: <span class="string">"production"</span>, <span class="comment">// "production" | "development" | "none"  // 提供 mode 配置选项，告知 webpack 使用相应模式的内置优化。</span></span><br><span class="line">  entry: <span class="string">"./app/entry"</span>, <span class="comment">// string | object | array  // 这里应用程序开始执行</span></span><br><span class="line">  <span class="comment">// webpack 开始打包</span></span><br><span class="line">  output: &#123;</span><br><span class="line">    <span class="comment">// webpack 如何输出结果的相关选项</span></span><br><span class="line">    path: path.resolve(__dirname, <span class="string">"dist"</span>), <span class="comment">// string</span></span><br><span class="line">    <span class="comment">// 所有输出文件的目标路径</span></span><br><span class="line">    <span class="comment">// 必须是绝对路径（使用 Node.js 的 path 模块）</span></span><br><span class="line">    filename: <span class="string">"bundle.js"</span>, <span class="comment">// string    // 「入口分块(entry chunk)」的文件名模板（出口分块？）</span></span><br><span class="line">    publicPath: <span class="string">"/assets/"</span>, <span class="comment">// string    // 输出解析文件的目录，url 相对于 HTML 页面</span></span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">  <span class="built_in">module</span>: &#123;</span><br><span class="line">    <span class="comment">// 关于模块配置</span></span><br><span class="line">    rules: [</span><br><span class="line">      <span class="comment">// 模块规则（配置 loader、解析器等选项）</span></span><br><span class="line">      &#123;</span><br><span class="line">        test: <span class="regexp">/\.html$/</span>,</span><br><span class="line">        use: [</span><br><span class="line">          <span class="comment">// 应用多个 loader 和选项</span></span><br><span class="line">          <span class="string">"htmllint-loader"</span>,</span><br><span class="line">          &#123;</span><br><span class="line">            loader: <span class="string">"html-loader"</span>,</span><br><span class="line">            options: &#123;</span><br><span class="line">              <span class="comment">/* ... */</span></span><br><span class="line">            &#125;</span><br><span class="line">          &#125;</span><br><span class="line">        ]</span><br><span class="line">      &#125;</span><br><span class="line">    ]</span><br><span class="line">  &#125;,</span><br><span class="line">  devtool: <span class="string">"source-map"</span>, <span class="comment">// 通过在浏览器调试工具(browser devtools)中添加元信息(meta info)增强调试</span></span><br><span class="line">  <span class="comment">// 牺牲了构建速度的 `source-map' 是最详细的。</span></span><br><span class="line"></span><br><span class="line">  devServer: &#123;</span><br><span class="line">    proxy: &#123; <span class="comment">// proxy URLs to backend development server</span></span><br><span class="line">      <span class="string">'/api'</span>: <span class="string">'http://localhost:3000'</span></span><br><span class="line">    &#125;,</span><br><span class="line">    contentBase: path.join(__dirname, <span class="string">'public'</span>), <span class="comment">// boolean | string | array, static file location</span></span><br><span class="line">    compress: <span class="literal">true</span>, <span class="comment">// enable gzip compression</span></span><br><span class="line">    historyApiFallback: <span class="literal">true</span>, <span class="comment">// true for index.html upon 404, object for multiple paths</span></span><br><span class="line">    hot: <span class="literal">true</span>, <span class="comment">// hot module replacement. Depends on HotModuleReplacementPlugin</span></span><br><span class="line">    https: <span class="literal">false</span>, <span class="comment">// true for self-signed, object for cert authority</span></span><br><span class="line">    noInfo: <span class="literal">true</span>, <span class="comment">// only errors &amp; warns on hot reload</span></span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">  &#125;,</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// 插件配置</span></span><br><span class="line">  plugins: [</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<hr>
<h1 id="loader-1"><a href="#loader-1" class="headerlink" title="loader"></a>loader</h1><p>webpack 可以使用 <code>loader</code> 来预处理文件。允许打包除 JavaScript 之外的任何静态资源。可以使用 Node.js 来很简单地编写自己的 <code>loader</code>。</p>
<p>这里列举一些分类的常用 <code>loader</code>。</p>
<h2 id="文件"><a href="#文件" class="headerlink" title="文件"></a>文件</h2><ul>
<li><code>raw-loader</code> 加载文件原始内容（utf-8）</li>
<li><code>val-loader</code> 将代码作为模块执行，并将 <code>exports</code> 转为 JS 代码</li>
<li><code>url-loader</code> 像 <code>file loader</code> 一样工作，但如果文件小于限制，可以返回 <code>data URL</code></li>
<li><code>file-loader</code> 将文件发送到输出文件夹，并返回（相对）<code>URL</code></li>
</ul>
<h2 id="JSON"><a href="#JSON" class="headerlink" title="JSON"></a>JSON</h2><ul>
<li><code>json-loader</code> 加载 JSON 文件（默认包含）</li>
<li><code>json5-loader</code> 加载和转译 JSON 5 文件</li>
<li><code>cson-loader</code> 加载和转译 CSON 文件</li>
</ul>
<h2 id="转换编译-Transpiling"><a href="#转换编译-Transpiling" class="headerlink" title="转换编译(Transpiling)"></a>转换编译(Transpiling)</h2><ul>
<li><code>script-loader</code> 在全局上下文中执行一次 JavaScript 文件（如在 script 标签），不需要解析</li>
<li><code>babel-loader</code> 加载 ES2015+ 代码，然后使用 Babel 转译为 ES5</li>
<li><code>buble-loader</code> 使用 Bublé 加载 ES2015+ 代码，并且将代码转译为 ES5</li>
<li><code>traceur-loader</code> 加载 ES2015+ 代码，然后使用 Traceur 转译为 ES5</li>
<li><code>ts-loader</code> 或 <code>awesome-typescript-loader</code> 像 JavaScript 一样加载 <code>TypeScript 2.0+</code></li>
<li><code>coffee-loader</code> 像 JavaScript 一样加载 <code>CoffeeScript</code></li>
</ul>
<h2 id="模板-Templating"><a href="#模板-Templating" class="headerlink" title="模板(Templating)"></a>模板(Templating)</h2><ul>
<li><code>html-loader</code> 导出 HTML 为字符串，需要引用静态资源</li>
<li><code>pug-loader</code> 加载 Pug 模板并返回一个函数</li>
<li><code>jade-loader</code> 加载 Jade 模板并返回一个函数</li>
<li><code>markdown-loader</code> 将 Markdown 转译为 HTML</li>
<li><code>react-markdown-loader</code> 使用 markdown-parse parser(解析器) 将 Markdown 编译为 React 组件</li>
<li><code>posthtml-loader</code> 使用 PostHTML 加载并转换 HTML 文件</li>
<li><code>handlebars-loader</code> 将 Handlebars 转移为 HTML</li>
<li><code>markup-inline-loader</code> 将内联的 SVG/MathML 文件转换为 HTML。在应用于图标字体，或将 CSS 动画应用于 SVG 时非常有用。</li>
</ul>
<h2 id="样式"><a href="#样式" class="headerlink" title="样式"></a>样式</h2><ul>
<li><code>style-loader</code> 将模块的导出作为样式添加到 DOM 中</li>
<li><code>css-loader</code> 解析 CSS 文件后，使用 import 加载，并且返回 CSS 代码</li>
<li><code>less-loader</code> 加载和转译 LESS 文件</li>
<li><code>sass-loader</code> 加载和转译 SASS/SCSS 文件</li>
<li><code>postcss-loader</code> 使用 PostCSS 加载和转译 CSS/SSS 文件</li>
<li><code>stylus-loader</code> 加载和转译 Stylus 文件</li>
</ul>
<h2 id="清理和测试-Linting-amp-amp-Testing"><a href="#清理和测试-Linting-amp-amp-Testing" class="headerlink" title="清理和测试(Linting &amp;&amp; Testing)"></a>清理和测试(Linting &amp;&amp; Testing)</h2><ul>
<li><code>mocha-loader</code> 使用 mocha 测试（浏览器/NodeJS）</li>
<li><code>eslint-loader</code> PreLoader，使用 ESLint 清理代码</li>
<li><code>jshint-loader</code> PreLoader，使用 JSHint 清理代码</li>
<li><code>jscs-loader</code> PreLoader，使用 JSCS 检查代码样式</li>
<li><code>coverjs-loader</code> PreLoader，使用 CoverJS 确定测试覆盖率</li>
</ul>
<h2 id="框架-Frameworks"><a href="#框架-Frameworks" class="headerlink" title="框架(Frameworks)"></a>框架(Frameworks)</h2><ul>
<li><code>vue-loader</code> 加载和转译 Vue 组件</li>
<li><code>polymer-loader</code> 使用选择预处理器(preprocessor)处理，并且 require() 类似一等模块(first-class)的 Web 组件</li>
<li><code>angular2-template-loader</code> 加载和转译 Angular 组件</li>
</ul>
<hr>
<h1 id="loader-用法"><a href="#loader-用法" class="headerlink" title="loader 用法"></a>loader 用法</h1><h2 id="加载-CSS"><a href="#加载-CSS" class="headerlink" title="加载 CSS"></a>加载 CSS</h2><p>为了从 JavaScript 模块中 <code>import</code> 一个 <code>CSS</code> 文件，需要在 <code>module</code> 配置中 安装并添加 <code>style-loader</code> 和 <code>css-loader</code>。</p>
<p><code>css-loader</code> 用于编译 <code>.css</code> 的样式文件，<code>style-loader</code> 用于将编译后的 <code>css</code> 生成 <code>style</code> 节点，通常两者配合使用。因此一般安装 <code>css-loader</code> 安装的同时，也配合安装 <code>style-loader</code>。</p>
<h3 id="安装-1"><a href="#安装-1" class="headerlink" title="安装"></a>安装</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev css-loader style-loader</span><br></pre></td></tr></table></figure>

<h3 id="用法"><a href="#用法" class="headerlink" title="用法"></a>用法</h3><p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  <span class="comment">// loader 配置</span></span><br><span class="line">  <span class="built_in">module</span>: &#123;</span><br><span class="line">    rules: [</span><br><span class="line">      &#123;</span><br><span class="line">        test: <span class="regexp">/\.css$/</span>,</span><br><span class="line">        use: [ </span><br><span class="line">        <span class="string">'style-loader'</span>, <span class="comment">// 将 JS 字符串生成为 style 节点</span></span><br><span class="line">        <span class="string">'css-loader'</span> <span class="comment">// 将 CSS 转化成 CommonJS 模块</span></span><br><span class="line">        ]</span><br><span class="line">      &#125;</span><br><span class="line">    ]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>webpack 根据正则表达式，来确定应该查找哪些文件，并将其提供给指定的 <code>loader</code> 。在这种情况下，以 <code>.css</code> 结尾的全部文件，都将被提供给 <code>style-loader</code> 和 <code>css-loader</code> 。</p>
<p>==<code>loader</code> 的执行顺序是从下往上，从右向左。== 比如，以上代码，先使用 <code>css-loader</code> 解析 <code>css</code> 文件，然后再将解析的 <code>css</code> 样式，编译为生成 <code>style</code> 节点。</p>
<h2 id="加载图片"><a href="#加载图片" class="headerlink" title="加载图片"></a>加载图片</h2><p><code>file-loader</code> 可以用来处理图片、图标等非 js 等文件编译。</p>
<h3 id="安装-2"><a href="#安装-2" class="headerlink" title="安装"></a>安装</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev file-loader</span><br></pre></td></tr></table></figure>

<h3 id="用法-1"><a href="#用法-1" class="headerlink" title="用法"></a>用法</h3><p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  <span class="built_in">module</span>: &#123;</span><br><span class="line">    rules: [</span><br><span class="line">     &#123;</span><br><span class="line">        test: <span class="regexp">/\.(png|svg|jpg|gif)$/</span>,</span><br><span class="line">        use: [</span><br><span class="line">          <span class="string">'file-loader'</span></span><br><span class="line">        ]</span><br><span class="line">      &#125;</span><br><span class="line">    ]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如果想压缩和优化图像。查看 <code>image-webpack-loader</code> 和 <code>url-loader</code>，以了解更多关于如何增强加载处理图片功能。</p>
<h2 id="加载字体"><a href="#加载字体" class="headerlink" title="加载字体"></a>加载字体</h2><p><code>file-loader</code> 和 <code>url-loader</code> 可以接收并加载任何文件，然后将其输出到构建目录。</p>
<h3 id="用法-2"><a href="#用法-2" class="headerlink" title="用法"></a>用法</h3><p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  <span class="built_in">module</span>: &#123;</span><br><span class="line">    rules: [</span><br><span class="line">     &#123;</span><br><span class="line">        test: <span class="regexp">/\.(woff|woff2|eot|ttf|otf)$/</span>,</span><br><span class="line">        use: [</span><br><span class="line">          <span class="string">'file-loader'</span></span><br><span class="line">        ]</span><br><span class="line">      &#125;</span><br><span class="line">    ]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>file-loader</code> 和 <code>url-loader</code> 的区别在于，<code>file-loader</code> 通常用于打包文件，生成静态文件。而 <code>url-loader</code> 可以进行生成文件的 <code>base64</code> 编码，从而直接写在代码里，避免生成文件。通常 <code>2kb</code> 以下的小图标、字体等小文件，建议采用 <code>url-loader</code> 打包，这样可以将来节省文件请求次数。具体详细用法，参考官方文档。</p>
<h2 id="处理-sass-scss-样式文件"><a href="#处理-sass-scss-样式文件" class="headerlink" title="处理 sass/scss 样式文件"></a>处理 sass/scss 样式文件</h2><p><code>sass-loader</code> 可以将 <code>sass/scss</code> 样式文件格式编译为 <code>css</code> 文件。</p>
<h3 id="安装-3"><a href="#安装-3" class="headerlink" title="安装"></a>安装</h3><p>==通常，一些 loader 不是单独安装的，会配合安装一些模块。比如 <code>sass-loader</code> 就还需要安装 <code>node-sass</code>。== 以官方文档安装步骤为准。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install sass-loader node-sass webpack --save-dev</span><br></pre></td></tr></table></figure>

<h3 id="用法-3"><a href="#用法-3" class="headerlink" title="用法"></a>用法</h3><p>通过将 <code>style-loader</code> 和 <code>css-loader</code> 与 <code>sass-loader</code> 链式调用，可以立刻将样式作用在 DOM 元素。</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  ...</span><br><span class="line">  <span class="built_in">module</span>: &#123;</span><br><span class="line">    rules: [&#123;</span><br><span class="line">      test: <span class="regexp">/\.scss$/</span>,</span><br><span class="line">      use: [&#123;</span><br><span class="line">          loader: <span class="string">"style-loader"</span> <span class="comment">// 将 JS 字符串生成为 style 节点</span></span><br><span class="line">      &#125;, &#123;</span><br><span class="line">          loader: <span class="string">"css-loader"</span> <span class="comment">// 将 CSS 转化成 CommonJS 模块</span></span><br><span class="line">      &#125;, &#123;</span><br><span class="line">          loader: <span class="string">"sass-loader"</span> <span class="comment">// 将 Sass 编译成 CSS</span></span><br><span class="line">      &#125;]</span><br><span class="line">    &#125;]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>==注意，使用多个 loader 时，loader 的执行顺序为 从右到左，从下到上。==</p>
<p>以上 <code>loader</code> 配置执行顺序是，先用 <code>sass-loader</code> 把 <code>sass</code> 文件编译为 <code>css</code> 文件，然后再用  <code>css-loader</code> 将 <code>css</code> 文件编译为模块，然后再用 <code>style-loader</code> 将样式生成 <code>style</code> 节点，挂载到页面。</p>
<h2 id="处理-css3-兼容前缀"><a href="#处理-css3-兼容前缀" class="headerlink" title="处理 css3 兼容前缀"></a>处理 css3 兼容前缀</h2><p><code>postcss-loader</code> 可以将打包编译过的 <code>css</code> 样式文件，自动添加一些兼容前缀，例如 <code>-webkit-</code> 等。</p>
<h3 id="安装-4"><a href="#安装-4" class="headerlink" title="安装"></a>安装</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev postcss-loader   &#x2F;&#x2F; 安装 postcss-loader</span><br><span class="line">npm install --save-dev autoprefixer   &#x2F;&#x2F; 安装 autoprefixer 自动加前缀插件</span><br></pre></td></tr></table></figure>

<h3 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h3><p>需要在 <em>webpack.config.js</em> 同级目录下创建 <em>postcss.config.js</em>，添加相关插件配置。</p>
<p><em>postcss.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    plugins: [</span><br><span class="line">        <span class="built_in">require</span>(<span class="string">'autoprefixer'</span>)</span><br><span class="line">    ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在 webpack 配置文件中添加样式相关等 <code>postcss-loader</code>。</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    entry: <span class="string">'./app.js'</span>,</span><br><span class="line">    output: &#123;</span><br><span class="line">        filename: <span class="string">'bundle.js'</span>,</span><br><span class="line">        path: path.resolve(__dirname, <span class="string">'dist'</span>)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="built_in">module</span>: &#123;</span><br><span class="line">        rules: [</span><br><span class="line">            &#123;</span><br><span class="line">                test: <span class="regexp">/\.css$/</span>,</span><br><span class="line">                use: [</span><br><span class="line">                    <span class="string">'style-loader'</span>,</span><br><span class="line">                    <span class="string">'css-loader'</span>,</span><br><span class="line">                    <span class="string">'postcss-loader'</span></span><br><span class="line">                ]</span><br><span class="line">            &#125;,</span><br><span class="line">            &#123;</span><br><span class="line">                test: <span class="regexp">/\.(jpg|png|jpeg|gif)$/</span>,</span><br><span class="line">                use: [<span class="string">"file-loader"</span>]</span><br><span class="line">            &#125;,</span><br><span class="line">            &#123;</span><br><span class="line">                test: <span class="regexp">/\.(scss|sass)$/</span>,</span><br><span class="line">                use: [<span class="string">"style-loader"</span>, <span class="string">"css-loader"</span>, <span class="string">"postcss-loader"</span>, <span class="string">"sass-loader"</span>]</span><br><span class="line">            &#125;</span><br><span class="line">        ]</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>webpack 4.X 以上，需要在 <code>package.json</code> 文件中配置浏览器支持参数 <code>browserslist</code>。</p>
<p><em>package.json</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="string">"name"</span>: <span class="string">"webpack-demo"</span>,</span><br><span class="line">  <span class="string">"version"</span>: <span class="string">"1.0.0"</span>,</span><br><span class="line">  <span class="string">"description"</span>: <span class="string">""</span>,</span><br><span class="line">  <span class="string">"main"</span>: <span class="string">"app.js"</span>,</span><br><span class="line">  <span class="string">"dependencies"</span>: &#123;</span><br><span class="line">    <span class="string">"webpack"</span>: <span class="string">"^4.42.1"</span>,</span><br><span class="line">    <span class="string">"webpack-cli"</span>: <span class="string">"^3.3.11"</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="string">"devDependencies"</span>: &#123;</span><br><span class="line">    <span class="string">"autoprefixer"</span>: <span class="string">"^9.7.6"</span>,</span><br><span class="line">    <span class="string">"css-loader"</span>: <span class="string">"^3.5.2"</span>,</span><br><span class="line">    <span class="string">"file-loader"</span>: <span class="string">"^6.0.0"</span>,</span><br><span class="line">    <span class="string">"node-sass"</span>: <span class="string">"^4.13.1"</span>,</span><br><span class="line">    <span class="string">"postcss-loader"</span>: <span class="string">"^3.0.0"</span>,</span><br><span class="line">    <span class="string">"sass-loader"</span>: <span class="string">"^8.0.2"</span>,</span><br><span class="line">    <span class="string">"style-loader"</span>: <span class="string">"^1.1.4"</span>,</span><br><span class="line">    <span class="string">"url-loader"</span>: <span class="string">"^4.1.0"</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="string">"scripts"</span>: &#123;</span><br><span class="line">    <span class="string">"build"</span>: <span class="string">"webpack"</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="string">"author"</span>: <span class="string">""</span>,</span><br><span class="line">  <span class="string">"license"</span>: <span class="string">"ISC"</span>,</span><br><span class="line">  <span class="string">"browserslist"</span>: [</span><br><span class="line">    <span class="string">"defaults"</span>,</span><br><span class="line">    <span class="string">"not ie &lt; 11"</span>,</span><br><span class="line">    <span class="string">"last 2 versions"</span>,</span><br><span class="line">    <span class="string">"&gt; 1%"</span>,</span><br><span class="line">    <span class="string">"iOS 7"</span>,</span><br><span class="line">    <span class="string">"last 3 iOS versions"</span></span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>然后在打包完成的项目样式就，就可以以看到添加了前缀的样式效果了。</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"><span class="selector-class">.pic-container</span> &#123;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">80px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">80px</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">100px</span>;</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">10px</span>;</span><br><span class="line">    <span class="attribute">-webkit-transform</span>: <span class="built_in">translate</span>(<span class="number">40px</span>, <span class="number">40px</span>);</span><br><span class="line">    <span class="attribute">transform</span>: <span class="built_in">translate</span>(<span class="number">40px</span>, <span class="number">40px</span>);</span><br><span class="line">&#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>

<hr>
<h1 id="Babel"><a href="#Babel" class="headerlink" title="Babel"></a>Babel</h1><p>Babel 是一个工具链，主要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法，以便能够运行在当前和旧版本的浏览器或其他环境中。在 webpack 中使用 babel 操作如下。</p>
<h2 id="安装-5"><a href="#安装-5" class="headerlink" title="安装"></a>安装</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev babel-loader @babel&#x2F;core</span><br></pre></td></tr></table></figure>

<h2 id="配置-1"><a href="#配置-1" class="headerlink" title="配置"></a>配置</h2><p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>: &#123;</span><br><span class="line">  rules: [</span><br><span class="line">    &#123;   </span><br><span class="line">        test: <span class="regexp">/\.js$/</span>, </span><br><span class="line">        exclude: <span class="regexp">/node_modules/</span>, <span class="comment">// 排除该目录下的转译</span></span><br><span class="line">        loader: <span class="string">"babel-loader"</span> <span class="comment">// webpack 和 babel 的桥梁</span></span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>babel-loader</code> 只是 <code>webpack</code> 和 <code>babel</code> 的桥梁，并不会真正的去将 ES6 打包降级。真正需要打包降级的是 <code>@babel/preset-env</code>。</p>
<h2 id="创建-babelrc-配置文件"><a href="#创建-babelrc-配置文件" class="headerlink" title="创建 .babelrc 配置文件"></a>创建 <code>.babelrc</code> 配置文件</h2><p>虽然已经配置好了 Babel ，但并没有让它真正生效。还需要在项目的根目录中创建一个 <code>.babelrc</code> 的配置文件并启用一些插件。</p>
<p>安装可以使用转换 ES2015+ 的 <code>env preset</code> 。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install @babel&#x2F;preset-env --save-dev</span><br></pre></td></tr></table></figure>

<p>为了让 <code>preset</code> 生效，需要像下面这样定义 <code>.babelrc</code> 文件：</p>
<p><em>.babelrc</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="string">"presets"</span>: [<span class="string">"@babel/preset-env"</span>]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这样打包编译过的 <code>bundle</code> 文件，就被降级处理过了。</p>
<hr>
<h1 id="插件用法"><a href="#插件用法" class="headerlink" title="插件用法"></a>插件用法</h1><p><code>plugins</code> 可以在 webpack 运行到某个时刻的时候，做一些事情，有点类似于生命周期。</p>
<p>这里列举几个常用插件配置用法。</p>
<h2 id="html-webpack-plugin"><a href="#html-webpack-plugin" class="headerlink" title="html-webpack-plugin"></a>html-webpack-plugin</h2><p>通常，打包过后的文件为 <code>js</code> 文件，用于网页，需要自行写入 <code>html</code> 文件，规定 DOM 根节点，自行引入打包过后的 <code>bundle.js</code> 文件。</p>
<p><code>HtmlWebpackPlugin</code> 插件会在打包结束后，自动生成一个 <code>html</code> 文件，并把打包生成的 <code>bundle.js</code> 文件自动引入到这个 <code>html</code> 文件中。</p>
<h3 id="安装-6"><a href="#安装-6" class="headerlink" title="安装"></a>安装</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev html-webpack-plugin</span><br></pre></td></tr></table></figure>

<h3 id="用法-4"><a href="#用法-4" class="headerlink" title="用法"></a>用法</h3><p>该插件将自动生成一个 HTML5 文件， 其中包括使用 <code>script</code> 标签的 <code>body</code> 中的所有 <code>webpack</code> 包。</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> HtmlWebpackPlugin = <span class="built_in">require</span>(<span class="string">'html-webpack-plugin'</span>);</span><br><span class="line"><span class="keyword">var</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> webpackConfig = &#123;</span><br><span class="line">  entry: <span class="string">'index.js'</span>,</span><br><span class="line">  output: &#123;</span><br><span class="line">    path: path.resolve(__dirname, <span class="string">'./dist'</span>),</span><br><span class="line">    filename: <span class="string">'index_bundle.js'</span></span><br><span class="line">  &#125;,</span><br><span class="line">  plugins: [<span class="keyword">new</span> HtmlWebpackPlugin()]</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>这将会产生一个包含以下内容的文件 <code>dist/index.html</code>，并且自动引入了包文件。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>webpack App<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"index_bundle.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>简单配置：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line">plugins:[<span class="keyword">new</span> HtmlWebpackPlugin(&#123;</span><br><span class="line">        title:<span class="string">'webpack学习'</span>,</span><br><span class="line">        filename:<span class="string">'assets/learn.html'</span>,</span><br><span class="line">        template:<span class="string">'./template.html'</span></span><br><span class="line">    &#125;)]</span><br><span class="line">...</span><br></pre></td></tr></table></figure>

<p>可以配置打包过后页面的头部 <code>title</code> 信息、在打包目录下的路径、或者以哪个 HTML 模板为参照，生成 HTML 文件等。</p>
<p>详细配置，参照官网：<a href="https://github.com/jantimon/html-webpack-plugin#configuration" target="_blank" rel="noopener">https://github.com/jantimon/html-webpack-plugin#configuration</a></p>
<h2 id="clean-webpack-plugin"><a href="#clean-webpack-plugin" class="headerlink" title="clean-webpack-plugin"></a>clean-webpack-plugin</h2><p>频繁修改 <em>webpack.config.js</em> 配置，会导致打包过后的 <code>dist</code> 文件夹输出文件的不断变化，但是每次并不会删减，只会替换和新增，一些无用的文件就会存在于 <code>dist</code> 文件夹中。通常每次打包都会手动删除 <code>dist</code> 文件夹，再重新打包生成。</p>
<p><code>clean-webpack-plugin</code> 可以每次自动删除清空你的打包项目的文件夹。</p>
<h3 id="安装-7"><a href="#安装-7" class="headerlink" title="安装"></a>安装</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev clean-webpack-plugin</span><br></pre></td></tr></table></figure>

<h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> &#123; CleanWebpackPlugin &#125; = <span class="built_in">require</span>(<span class="string">'clean-webpack-plugin'</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> webpackConfig = &#123;</span><br><span class="line">    plugins: [</span><br><span class="line">        <span class="keyword">new</span> CleanWebpackPlugin(),</span><br><span class="line">    ],</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = webpackConfig;</span><br></pre></td></tr></table></figure>

<p>默认不需要进行配置即可使用，自动清空打包目录。==注意写法方式是 <code>{ CleanWebpackPlugin }</code> 引入，大括号和大驼峰命名。==</p>
<p>详细用法，参照官网：<a href="https://github.com/johnagan/clean-webpack-plugin" target="_blank" rel="noopener">https://github.com/johnagan/clean-webpack-plugin</a></p>
<hr>
<h1 id="多入口打包配置"><a href="#多入口打包配置" class="headerlink" title="多入口打包配置"></a>多入口打包配置</h1><p>将文件打包为多入口，并且实现自动添加 CDN 地址链接。</p>
<p><code>output</code> 采用占位符 <code>[name].js</code> 写法、<code>publicPath</code> 配置 CDN 域名。</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    mode:<span class="string">'development'</span>,</span><br><span class="line">    entry: &#123;</span><br><span class="line">        main:<span class="string">'./app.js'</span>,</span><br><span class="line">        sub:<span class="string">'./app.js'</span></span><br><span class="line">    &#125;,</span><br><span class="line">    output: &#123;</span><br><span class="line">        filename: <span class="string">'[name].js'</span>,</span><br><span class="line">        publicPath:<span class="string">'http://guopengsong.cdn/'</span>,</span><br><span class="line">        path: path.resolve(__dirname, <span class="string">'dist'</span>)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="built_in">module</span>: &#123;</span><br><span class="line">      ...</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><em>/dist 目录</em></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">webpack-demo</span><br><span class="line">|- package.json</span><br><span class="line">|- webpack.config.js</span><br><span class="line">|- &#x2F;dist</span><br><span class="line">  |- main.js</span><br><span class="line">  |- sub.js</span><br><span class="line">  |- index.html</span><br><span class="line">|- &#x2F;src</span><br><span class="line">  |- index.js</span><br><span class="line">|- &#x2F;node_modules</span><br></pre></td></tr></table></figure>

<p><em>/dist/index.html</em></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>模板文件<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"root"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"http://guopengsong.cdn/main.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"http://guopengsong.cdn/sub.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<hr>
<h1 id="source-map"><a href="#source-map" class="headerlink" title="source map"></a>source map</h1><p>开发过程中，需要实时调试报错代码，定位问题代码具体文件、行数信息。如果不使用 <code>source map</code> ，则看到的是打包过后的源代码，比较混乱。无法直观、精准的定位到目前正在开发的源代码，源文件的具体位置。</p>
<p><code>source map</code> 是一个映射关系。举例来说，它可以定位到打包目录 <code>/dist</code> 下 <code>main.js</code> 文件的 <code>96</code> 行实际对应到是 <code>/src</code> 目录下的 <code>index.js</code> 文件中的第 <code>3</code> 行。<code>index.js</code> 是我们实时开发的源代码，定位到具体位置后，方便代码调试。</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"></span><br><span class="line">module.exports &#x3D; &#123;</span><br><span class="line">    ...</span><br><span class="line">    mode: &#39;development&#39;,</span><br><span class="line">    devtool: &#39;cheap-source-map&#39;,</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>通过配置 <code>devtool</code> 值的不同，从而实现不同的 <code>source map</code>  配置，不同的配置参数会影响打包速度、映射显示的不同。</p>
<p>常用配置文档说明参考：</p>
<ul>
<li><code>inline</code> 表示打包生成的文件 <code>map</code> 映射，集成到打包生成的 <code>main.js</code> 文件中。</li>
<li><code>cheap</code> 只提示行，不提示列的报错信息，只提示业务代码，不提示 <code>loader</code> 等插件等问题的报错信息。</li>
<li><code>module</code> 表示不仅提供业务代码报错信息，还提示 <code>模块、loader</code> 等报错信息。</li>
<li><code>eval</code> 配合 <code>source-map</code> 提高速度。</li>
<li><code>source-map</code> 生成 <code>.map</code> 映射文件。</li>
</ul>
<p>日常实践，==对于开发环境而言，建议设置值为：<code>cheap-module-eval-source-map</code>。对于生产环境的代码，可以设置为 none，以提升打包速度，不生成映射关系。但是如果需要生产环境的代码报错时，也能看到报错信息，可以设置为 <code>cheap-module-source-map</code>。==</p>
<p>详细配置可以参考官网：<a href="https://www.webpackjs.com/configuration/devtool/" target="_blank" rel="noopener">https://www.webpackjs.com/configuration/devtool/</a></p>
<hr>
<h1 id="webpack-dev-server"><a href="#webpack-dev-server" class="headerlink" title="webpack-dev-server"></a>webpack-dev-server</h1><p><code>webpack-dev-server</code> 提供了一个简单的 <code>web</code> 服务器，并且能够实时重新加载(<code>live reloading</code>)。<code>webpack-dev-server</code> 打包过的文件存在于内存中，所以不会出现在 <code>/dist</code> 目录中，这是为了提升速度。</p>
<h2 id="安装-8"><a href="#安装-8" class="headerlink" title="安装"></a>安装</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev webpack-dev-server</span><br></pre></td></tr></table></figure>

<h2 id="配置-2"><a href="#配置-2" class="headerlink" title="配置"></a>配置</h2><p>修改配置文件，告诉开发服务器(<code>dev server</code>)，在哪里查找文件：</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">const path &#x3D; require(&#39;path&#39;);</span><br><span class="line">const HtmlWebpackPlugin &#x3D; require(&#39;html-webpack-plugin&#39;);</span><br><span class="line">const CleanWebpackPlugin &#x3D; require(&#39;clean-webpack-plugin&#39;);</span><br><span class="line"></span><br><span class="line">module.exports &#x3D; &#123;</span><br><span class="line">  entry: &#123;</span><br><span class="line">    app: &#39;.&#x2F;src&#x2F;index.js&#39;,</span><br><span class="line">    print: &#39;.&#x2F;src&#x2F;print.js&#39;</span><br><span class="line">  &#125;,</span><br><span class="line">  devtool: &#39;inline-source-map&#39;,</span><br><span class="line">  devServer: &#123;</span><br><span class="line">    contentBase: &#39;.&#x2F;dist&#39;</span><br><span class="line">  &#125;,</span><br><span class="line">  plugins: [</span><br><span class="line">    new CleanWebpackPlugin([&#39;dist&#39;]),</span><br><span class="line">    new HtmlWebpackPlugin(&#123;</span><br><span class="line">      title: &#39;Development&#39;</span><br><span class="line">    &#125;)</span><br><span class="line">  ],</span><br><span class="line">  output: &#123;</span><br><span class="line">    filename: &#39;[name].bundle.js&#39;,</span><br><span class="line">    path: path.resolve(__dirname, &#39;dist&#39;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>以上配置告知 <code>webpack-dev-server</code>，在 <code>localhost:8080</code> (默认，可以通过配置修改)下建立服务，将 <code>dist</code> 目录下的文件，作为可访问文件。</p>
<p>配置文档：<a href="https://www.webpackjs.com/configuration/dev-server/#devserver-proxy" target="_blank" rel="noopener">https://www.webpackjs.com/configuration/dev-server/#devserver-proxy</a></p>
<p>添加一个 <code>script</code> 脚本，可以直接运行开发服务器(<code>dev server</code>)：</p>
<p><em>package.json</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="string">"name"</span>: <span class="string">"development"</span>,</span><br><span class="line">    <span class="string">"version"</span>: <span class="string">"1.0.0"</span>,</span><br><span class="line">    <span class="string">"description"</span>: <span class="string">""</span>,</span><br><span class="line">    <span class="string">"main"</span>: <span class="string">"webpack.config.js"</span>,</span><br><span class="line">    <span class="string">"scripts"</span>: &#123;</span><br><span class="line">      <span class="string">"watch"</span>: <span class="string">"webpack --watch"</span>,</span><br><span class="line">      <span class="string">"start"</span>: <span class="string">"webpack-dev-server --open"</span>,</span><br><span class="line">      <span class="string">"build"</span>: <span class="string">"webpack"</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">"keywords"</span>: [],</span><br><span class="line">    <span class="string">"author"</span>: <span class="string">""</span>,</span><br><span class="line">    <span class="string">"license"</span>: <span class="string">"ISC"</span>,</span><br><span class="line">    <span class="string">"devDependencies"</span>: &#123;</span><br><span class="line">      <span class="string">"clean-webpack-plugin"</span>: <span class="string">"^0.1.16"</span>,</span><br><span class="line">      <span class="string">"css-loader"</span>: <span class="string">"^0.28.4"</span>,</span><br><span class="line">      <span class="string">"csv-loader"</span>: <span class="string">"^2.1.1"</span>,</span><br><span class="line">      <span class="string">"file-loader"</span>: <span class="string">"^0.11.2"</span>,</span><br><span class="line">      <span class="string">"html-webpack-plugin"</span>: <span class="string">"^2.29.0"</span>,</span><br><span class="line">      <span class="string">"style-loader"</span>: <span class="string">"^0.18.2"</span>,</span><br><span class="line">      <span class="string">"webpack"</span>: <span class="string">"^3.0.0"</span>,</span><br><span class="line">      <span class="string">"xml-loader"</span>: <span class="string">"^1.2.1"</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>可以在命令行中运行 <code>npm start</code>，就会看到浏览器自动加载页面。如果现在修改和保存任意源文件，<code>web</code> 服务器就会自动重新加载编译后的代码。</p>
<hr>
<h1 id="模块热替换（HMR）"><a href="#模块热替换（HMR）" class="headerlink" title="模块热替换（HMR）"></a>模块热替换（HMR）</h1><p>略</p>
<hr>
<h1 id="tree-shaking"><a href="#tree-shaking" class="headerlink" title="tree shaking"></a>tree shaking</h1><p><code>tree shaking</code> 是一个术语，通常用于描述==移除 JavaScript 上下文中的未引用代码。== 它依赖于 ES2015 模块系统中的静态结构特性，例如 <code>import</code> 和 <code>export</code>。（==该功能只能用于 ES6 模块，不能用于<code>common JS</code> 或其它动态模块方案==）。</p>
<p>新的 webpack 4 正式版本，扩展了这个检测能力，通过 <code>package.json</code> 的 <code>&quot;sideEffects&quot;</code> 属性作为标记，向 <code>compiler</code> 提供提示，表明项目中的哪些文件是 <code>&quot;pure(纯的 ES2015 模块)&quot;</code>，由此可以安全地删除文件中未使用的部分。</p>
<h2 id="将文件标记为无副作用-side-effect-free"><a href="#将文件标记为无副作用-side-effect-free" class="headerlink" title="将文件标记为无副作用(side-effect-free)"></a>将文件标记为无副作用(side-effect-free)</h2><p>在一个纯粹的 ESM 模块世界中，识别出哪些文件有副作用很简单。然而，我们的项目无法达到这种纯度，所以，此时有必要向 webpack 的 <code>compiler</code> 提供提示哪些代码是“纯粹部分”。</p>
<p>这种方式是通过 <code>package.json</code> 的 <code>&quot;sideEffects&quot;</code> 属性来实现的。</p>
<p>如果所有代码都不包含副作用，我们就可以简单地将该属性标记为 <code>false</code>，来告知 webpack，它可以安全地删除未用到的 <code>export</code> 导出。</p>
<p><em>package.json</em></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"name"</span>: <span class="string">"your-project"</span>,</span><br><span class="line">  <span class="attr">"sideEffects"</span>: <span class="literal">false</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>==直接设置 <code>sideEffects</code> 的值为 <code>false</code> ，有很大的风险，尤其生产模式下，即 <code>mode</code> 的值为 <code>production</code>，会将一些引入的样式文件、插件、静态文件等给排除在外。==</p>
<p>如果你的部分模块代码确实有一些副作用，那么可以改为提供一个数组：</p>
<p><em>package.json</em></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"name"</span>: <span class="string">"your-project"</span>,</span><br><span class="line">  <span class="attr">"sideEffects"</span>: [</span><br><span class="line">    <span class="string">"./src/some-side-effectful-file.js"</span>,</span><br><span class="line">    <span class="string">"*.css"</span>,</span><br><span class="line">    <span class="string">"*.scss"</span></span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>以上配置是将 <code>some-side-effectful-file.js、*.css、*.scss</code> 等文件排除在 <code>tree shaking</code> 之外。</p>
<h2 id="压缩输出"><a href="#压缩输出" class="headerlink" title="压缩输出"></a>压缩输出</h2><p>通过如上方式，我们已经可以通过 <code>import</code> 和 <code>export</code> 语法，找出那些需要删除的“未使用代码”，然而，我们不只是要找出，还需要在 <code>bundle</code> 中删除它们。</p>
<p>==从 webpack 4 开始，可以通过 <code>&quot;mode&quot;</code> 配置选项轻松切换到压缩输出，只需设置为 <code>&quot;production&quot;</code>。==</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  entry: <span class="string">'./src/index.js'</span>,</span><br><span class="line">  output: &#123;</span><br><span class="line">    filename: <span class="string">'bundle.js'</span>,</span><br><span class="line">    path: path.resolve(__dirname, <span class="string">'dist'</span>)</span><br><span class="line">  &#125;,</span><br><span class="line">  mode: <span class="string">"production"</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<hr>
<h1 id="生产环境构建"><a href="#生产环境构建" class="headerlink" title="生产环境构建"></a>生产环境构建</h1><p>开发环境(<code>development</code>)和生产环境(<code>production</code>)的构建目标差异很大。</p>
<p>在开发环境中，通常==需要具有强大的、具有实时重新加载(<code>live reloading</code>)或热模块替换(<code>hot module replacement</code>)能力的 <code>source map</code> 和 <code>localhost server</code>。==</p>
<p>而在生产环境中，通常的目标则转向于关注==更小的 <code>bundle</code>，更轻量的 <code>source map</code>，以及更优化的资源，以改善加载时间。==</p>
<p>由于要遵循逻辑分离，通常建议为每个环境编写彼此独立的 webpack 配置。</p>
<h2 id="webpack-merge"><a href="#webpack-merge" class="headerlink" title="webpack-merge"></a>webpack-merge</h2><p>生产环境和开发环境做了略微区分，但是，为了遵循不重复原则(Don’t repeat yourself - DRY)，保留一个“通用”配置。将这些配置合并在一起，使用一个名为 <code>webpack-merge</code> 的工具。通过“通用”配置，不必在环境特的配置中重复代码。</p>
<h3 id="安装-9"><a href="#安装-9" class="headerlink" title="安装"></a>安装</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev webpack-merge</span><br></pre></td></tr></table></figure>

<h3 id="配置使用"><a href="#配置使用" class="headerlink" title="配置使用"></a>配置使用</h3><p>项目目录</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">  webpack-demo</span><br><span class="line">  |- package.json</span><br><span class="line">- |- webpack.config.js</span><br><span class="line">+ |- webpack.common.js</span><br><span class="line">+ |- webpack.dev.js</span><br><span class="line">+ |- webpack.prod.js</span><br><span class="line">  |- &#x2F;dist</span><br><span class="line">  |- &#x2F;src</span><br><span class="line">    |- index.js</span><br><span class="line">    |- math.js</span><br><span class="line">  |- &#x2F;node_modules</span><br></pre></td></tr></table></figure>

<p>公共配置 <em>webpack.common.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"><span class="keyword">const</span> CleanWebpackPlugin = <span class="built_in">require</span>(<span class="string">'clean-webpack-plugin'</span>);</span><br><span class="line"><span class="keyword">const</span> HtmlWebpackPlugin = <span class="built_in">require</span>(<span class="string">'html-webpack-plugin'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  entry: &#123;</span><br><span class="line">    app: <span class="string">'./src/index.js'</span></span><br><span class="line">  &#125;,</span><br><span class="line">  plugins: [</span><br><span class="line">    <span class="keyword">new</span> CleanWebpackPlugin([<span class="string">'dist'</span>]),</span><br><span class="line">    <span class="keyword">new</span> HtmlWebpackPlugin(&#123;</span><br><span class="line">      title: <span class="string">'Production'</span></span><br><span class="line">    &#125;)</span><br><span class="line">  ],</span><br><span class="line">  output: &#123;</span><br><span class="line">    filename: <span class="string">'[name].bundle.js'</span>,</span><br><span class="line">    path: path.resolve(__dirname, <span class="string">'dist'</span>)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>开发环境下的配置 <em>webpack.dev.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> merge = <span class="built_in">require</span>(<span class="string">'webpack-merge'</span>);</span><br><span class="line"><span class="keyword">const</span> common = <span class="built_in">require</span>(<span class="string">'./webpack.common.js'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = merge(common, &#123;</span><br><span class="line">  devtool: <span class="string">'inline-source-map'</span>,</span><br><span class="line">  devServer: &#123;</span><br><span class="line">    contentBase: <span class="string">'./dist'</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>生产环境下的配置 <em>webpack.prod.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> merge = <span class="built_in">require</span>(<span class="string">'webpack-merge'</span>);</span><br><span class="line"><span class="keyword">const</span> UglifyJSPlugin = <span class="built_in">require</span>(<span class="string">'uglifyjs-webpack-plugin'</span>);</span><br><span class="line"><span class="keyword">const</span> common = <span class="built_in">require</span>(<span class="string">'./webpack.common.js'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = merge(common, &#123;</span><br><span class="line">  plugins: [</span><br><span class="line">    <span class="keyword">new</span> UglifyJSPlugin()</span><br><span class="line">  ]</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<h2 id="NPM-Scripts"><a href="#NPM-Scripts" class="headerlink" title="NPM Scripts"></a>NPM Scripts</h2><p>把 <code>scripts</code> 重新指向到新配置。将 <code>npm start</code> 定义为开发环境脚本，并在其中使用 <code>webpack-dev-server</code>，将 <code>npm run build</code> 定义为生产环境脚本。</p>
<p><em>package.json</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="string">"name"</span>: <span class="string">"development"</span>,</span><br><span class="line">  <span class="string">"version"</span>: <span class="string">"1.0.0"</span>,</span><br><span class="line">  <span class="string">"description"</span>: <span class="string">""</span>,</span><br><span class="line">  <span class="string">"main"</span>: <span class="string">"webpack.config.js"</span>,</span><br><span class="line">  <span class="string">"scripts"</span>: &#123;</span><br><span class="line">   <span class="string">"start"</span>: <span class="string">"webpack-dev-server --open --config webpack.dev.js"</span>,</span><br><span class="line">   <span class="string">"build"</span>: <span class="string">"webpack --config webpack.prod.js"</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="string">"keywords"</span>: [],</span><br><span class="line">  <span class="string">"author"</span>: <span class="string">""</span>,</span><br><span class="line">  <span class="string">"license"</span>: <span class="string">"ISC"</span>,</span><br><span class="line">  <span class="string">"devDependencies"</span>: &#123;</span><br><span class="line">    <span class="string">"clean-webpack-plugin"</span>: <span class="string">"^0.1.17"</span>,</span><br><span class="line">    <span class="string">"css-loader"</span>: <span class="string">"^0.28.4"</span>,</span><br><span class="line">    <span class="string">"csv-loader"</span>: <span class="string">"^2.1.1"</span>,</span><br><span class="line">    <span class="string">"express"</span>: <span class="string">"^4.15.3"</span>,</span><br><span class="line">    <span class="string">"file-loader"</span>: <span class="string">"^0.11.2"</span>,</span><br><span class="line">    <span class="string">"html-webpack-plugin"</span>: <span class="string">"^2.29.0"</span>,</span><br><span class="line">    <span class="string">"style-loader"</span>: <span class="string">"^0.18.2"</span>,</span><br><span class="line">    <span class="string">"webpack"</span>: <span class="string">"^3.0.0"</span>,</span><br><span class="line">    <span class="string">"webpack-dev-middleware"</span>: <span class="string">"^1.12.0"</span>,</span><br><span class="line">    <span class="string">"webpack-dev-server"</span>: <span class="string">"^2.9.1"</span>,</span><br><span class="line">    <span class="string">"webpack-merge"</span>: <span class="string">"^4.1.0"</span>,</span><br><span class="line">    <span class="string">"xml-loader"</span>: <span class="string">"^1.2.1"</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<hr>
<h1 id="代码分离"><a href="#代码分离" class="headerlink" title="代码分离"></a>代码分离</h1><p>代码分离能够把代码分离到不同的 <code>bundle</code> 中，然后可以按需加载或并行加载这些文件。代码分离可以用于获取更小的 <code>bundle</code>，以及控制资源加载优先级，如果使用合理，会极大节省加载时间。</p>
<p>有三种常用的代码分离方法：</p>
<ul>
<li>入口起点：使用 <code>entry</code> 配置手动地分离代码。</li>
<li>防止重复：使用 <code>CommonsChunkPlugin</code> 去重和分离 <code>chunk</code>。</li>
<li>动态导入：通过模块的内联函数调用来分离代码。</li>
</ul>
<h2 id="入口起点（配置-entry）"><a href="#入口起点（配置-entry）" class="headerlink" title="入口起点（配置 entry）"></a>入口起点（配置 <code>entry</code>）</h2><p>使用 <code>entry</code> 配置手动地分离代码。</p>
<p>优点：</p>
<ul>
<li>代码分离方式优点是简单、直观</li>
</ul>
<p>缺点：</p>
<ul>
<li>手动配置较多</li>
<li>如果入口 <code>chunks</code> 之间包含重复的模块，那些重复模块都会被引入到各个 <code>bundle</code> 中</li>
<li>这种方法不够灵活，并且不能将核心应用程序逻辑进行动态拆分代码</li>
</ul>
<p><em>project</em></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">webpack-demo</span><br><span class="line">|- package.json</span><br><span class="line">|- webpack.config.js</span><br><span class="line">|- &#x2F;dist</span><br><span class="line">|- &#x2F;src</span><br><span class="line">  |- index.js</span><br><span class="line">  |- another-module.js</span><br><span class="line">|- &#x2F;node_modules</span><br></pre></td></tr></table></figure>

<p><em>another-module.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> _ <span class="keyword">from</span> <span class="string">'lodash'</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(</span><br><span class="line">  _.join([<span class="string">'Another'</span>, <span class="string">'module'</span>, <span class="string">'loaded!'</span>], <span class="string">' '</span>)</span><br><span class="line">);</span><br></pre></td></tr></table></figure>

<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"><span class="keyword">const</span> HTMLWebpackPlugin = <span class="built_in">require</span>(<span class="string">'html-webpack-plugin'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  entry: &#123;</span><br><span class="line">    index: <span class="string">'./src/index.js'</span>,</span><br><span class="line">    another: <span class="string">'./src/another-module.js'</span></span><br><span class="line">  &#125;,</span><br><span class="line">  plugins: [</span><br><span class="line">    <span class="keyword">new</span> HTMLWebpackPlugin(&#123;</span><br><span class="line">      title: <span class="string">'Code Splitting'</span></span><br><span class="line">    &#125;)</span><br><span class="line">  ],</span><br><span class="line">  output: &#123;</span><br><span class="line">    filename: <span class="string">'[name].bundle.js'</span>,</span><br><span class="line">    path: path.resolve(__dirname, <span class="string">'dist'</span>)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>这将生成如下构建结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Hash: 309402710a14167f42a8</span><br><span class="line">Version: webpack 2.6.1</span><br><span class="line">Time: 570ms</span><br><span class="line">            Asset    Size  Chunks                    Chunk Names</span><br><span class="line">  index.bundle.js  544 kB       0  [emitted]  [big]  index</span><br><span class="line">another.bundle.js  544 kB       1  [emitted]  [big]  another</span><br><span class="line">   [0] .&#x2F;~&#x2F;lodash&#x2F;lodash.js 540 kB &#123;0&#125; &#123;1&#125; [built]</span><br><span class="line">   [1] (webpack)&#x2F;buildin&#x2F;global.js 509 bytes &#123;0&#125; &#123;1&#125; [built]</span><br><span class="line">   [2] (webpack)&#x2F;buildin&#x2F;module.js 517 bytes &#123;0&#125; &#123;1&#125; [built]</span><br><span class="line">   [3] .&#x2F;src&#x2F;another-module.js 87 bytes &#123;1&#125; [built]</span><br><span class="line">   [4] .&#x2F;src&#x2F;index.js 216 bytes &#123;0&#125; [built]</span><br></pre></td></tr></table></figure>

<p><code>lodash</code> 库被重复打包到了 <code>index.bundle.js</code> 和 <code>another.bundle.js</code>，造成了浪费。</p>
<h2 id="防止重复（使用-CommonsChunkPlugin）"><a href="#防止重复（使用-CommonsChunkPlugin）" class="headerlink" title="防止重复（使用 CommonsChunkPlugin）"></a>防止重复（使用 <code>CommonsChunkPlugin</code>）</h2><p><code>CommonsChunkPlugin</code> 插件，是一个可选的用于建立一个独立文件(又称作 <code>chunk</code>)的功能，这个文件包括多个入口 <code>chunk</code> 的公共模块。</p>
<p>注意：==<code>CommonsChunkPlugin</code> 已经从 <code>webpack v4 legato</code> 中移除。想要了解在最新版本中如何处理 <code>chunk</code>，请查看 <code>SplitChunksPlugin</code>。==</p>
<p>==通过将公共模块拆出来，最终合成的文件能够在最开始的时候加载一次，便存到缓存中供后续使用。== 这个带来速度上的提升，因为浏览器会迅速将公共的代码从缓存中取出来，而不是每次访问一个新页面时，再去加载一个更大的文件。</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"><span class="keyword">const</span> webpack = <span class="built_in">require</span>(<span class="string">'webpack'</span>);</span><br><span class="line"><span class="keyword">const</span> HTMLWebpackPlugin = <span class="built_in">require</span>(<span class="string">'html-webpack-plugin'</span>);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">module</span>.exports = &#123;</span><br><span class="line">   entry: &#123;</span><br><span class="line">     index: <span class="string">'./src/index.js'</span>,</span><br><span class="line">     another: <span class="string">'./src/another-module.js'</span></span><br><span class="line">   &#125;,</span><br><span class="line">   plugins: [</span><br><span class="line">     <span class="keyword">new</span> HTMLWebpackPlugin(&#123;</span><br><span class="line">       title: <span class="string">'Code Splitting'</span></span><br><span class="line">     &#125;),</span><br><span class="line">     <span class="keyword">new</span> webpack.optimize.CommonsChunkPlugin(&#123;</span><br><span class="line">       name: <span class="string">'common'</span> <span class="comment">// 指定公共 bundle 的名称。</span></span><br><span class="line">     &#125;)</span><br><span class="line">   ],</span><br><span class="line">   output: &#123;</span><br><span class="line">     filename: <span class="string">'[name].bundle.js'</span>,</span><br><span class="line">     path: path.resolve(__dirname, <span class="string">'dist'</span>)</span><br><span class="line">   &#125;</span><br><span class="line"> &#125;;</span><br></pre></td></tr></table></figure>

<p>配置：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  name: string, &#x2F;&#x2F; or</span><br><span class="line">  names: string[],</span><br><span class="line">  &#x2F;&#x2F; 这是 common chunk 的名称。已经存在的 chunk 可以通过传入一个已存在的 chunk 名称而被选择。</span><br><span class="line">  &#x2F;&#x2F; 如果一个字符串数组被传入，这相当于插件针对每个 chunk 名被多次调用</span><br><span class="line">  &#x2F;&#x2F; 如果该选项被忽略，同时 &#96;options.async&#96; 或者 &#96;options.children&#96; 被设置，所有的 chunk 都会被使用，</span><br><span class="line">  &#x2F;&#x2F; 否则 &#96;options.filename&#96; 会用于作为 chunk 名。</span><br><span class="line">  &#x2F;&#x2F; When using &#96;options.async&#96; to create common chunks from other async chunks you must specify an entry-point</span><br><span class="line">  &#x2F;&#x2F; chunk name here instead of omitting the &#96;option.name&#96;.</span><br><span class="line"></span><br><span class="line">  filename: string,</span><br><span class="line">  &#x2F;&#x2F; common chunk 的文件名模板。可以包含与 &#96;output.filename&#96; 相同的占位符。</span><br><span class="line">  &#x2F;&#x2F; 如果被忽略，原本的文件名不会被修改(通常是 &#96;output.filename&#96; 或者 &#96;output.chunkFilename&#96;)。</span><br><span class="line">  &#x2F;&#x2F; This option is not permitted if you&#39;re using &#96;options.async&#96; as well, see below for more details.</span><br><span class="line"></span><br><span class="line">  minChunks: number|Infinity|function(module, count) -&gt; boolean,</span><br><span class="line">  &#x2F;&#x2F; 在传入  公共chunk(commons chunk) 之前所需要包含的最少数量的 chunks 。</span><br><span class="line">  &#x2F;&#x2F; 数量必须大于等于2，或者少于等于 chunks的数量</span><br><span class="line">  &#x2F;&#x2F; 传入 &#96;Infinity&#96; 会马上生成 公共chunk，但里面没有模块。</span><br><span class="line">  &#x2F;&#x2F; 你可以传入一个 &#96;function&#96; ，以添加定制的逻辑（默认是 chunk 的数量）</span><br><span class="line"></span><br><span class="line">  chunks: string[],</span><br><span class="line">  &#x2F;&#x2F; 通过 chunk name 去选择 chunks 的来源。chunk 必须是  公共chunk 的子模块。</span><br><span class="line">  &#x2F;&#x2F; 如果被忽略，所有的，所有的 入口chunk (entry chunk) 都会被选择。</span><br><span class="line"></span><br><span class="line">  children: boolean,</span><br><span class="line">  &#x2F;&#x2F; 如果设置为 &#96;true&#96;，所有公共 chunk 的子模块都会被选择</span><br><span class="line"></span><br><span class="line">  deepChildren: boolean,</span><br><span class="line">  &#x2F;&#x2F; 如果设置为 &#96;true&#96;，所有公共 chunk 的后代模块都会被选择</span><br><span class="line"></span><br><span class="line">  async: boolean|string,</span><br><span class="line">  &#x2F;&#x2F; 如果设置为 &#96;true&#96;，一个异步的  公共chunk 会作为 &#96;options.name&#96; 的子模块，和 &#96;options.chunks&#96; 的兄弟模块被创建。</span><br><span class="line">  &#x2F;&#x2F; 它会与 &#96;options.chunks&#96; 并行被加载。</span><br><span class="line">  &#x2F;&#x2F; Instead of using &#96;option.filename&#96;, it is possible to change the name of the output file by providing</span><br><span class="line">  &#x2F;&#x2F; the desired string here instead of &#96;true&#96;.</span><br><span class="line"></span><br><span class="line">  minSize: number,</span><br><span class="line">  &#x2F;&#x2F; 在 公共chunk 被创建立之前，所有 公共模块 (common module) 的最少大小。</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="SplitChunksPlugin"><a href="#SplitChunksPlugin" class="headerlink" title="SplitChunksPlugin"></a>SplitChunksPlugin</h2><p><code>optimization.splitChunks</code>  有默认的配置项，如果在配置文件中开启了该属性，但是没有配置任何参数的话，也是起作用的，因为该属性有默认配置项。例如：</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    entry: <span class="string">'./app.js'</span>,</span><br><span class="line">    output: &#123;</span><br><span class="line">        filename: <span class="string">'bundle.js'</span>,</span><br><span class="line">        path: path.resolve(__dirname, <span class="string">'./dist'</span>)</span><br><span class="line">    &#125;,</span><br><span class="line">    optimization: &#123;</span><br><span class="line">        splitChunks: &#123;&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>此时也是起作用的，默认配置项目如下：</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    entry: <span class="string">'./app.js'</span>,</span><br><span class="line">    output: &#123;</span><br><span class="line">        filename: <span class="string">'bundle.js'</span>,</span><br><span class="line">        path: path.resolve(__dirname, <span class="string">'./dist'</span>)</span><br><span class="line">    &#125;,</span><br><span class="line">    optimization: &#123;</span><br><span class="line">        splitChunks: &#123;</span><br><span class="line">            chunks: <span class="string">"async"</span>,</span><br><span class="line">            minSize: <span class="number">30000</span>,</span><br><span class="line">            minChunks: <span class="number">1</span>,</span><br><span class="line">            maxAsyncRequests: <span class="number">5</span>,</span><br><span class="line">            maxInitialRequests: <span class="number">3</span>,</span><br><span class="line">            automaticNameDelimiter: <span class="string">'~'</span>,</span><br><span class="line">            name: <span class="literal">true</span>,</span><br><span class="line">            cacheGroups: &#123;</span><br><span class="line">                vendors: &#123;</span><br><span class="line">                    test: <span class="regexp">/[\\/]node_modules[\\/]/</span>,</span><br><span class="line">                    priority: <span class="number">-10</span></span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="keyword">default</span>: &#123;</span><br><span class="line">                    minChunks: <span class="number">2</span>,</span><br><span class="line">                    priority: <span class="number">-20</span>,</span><br><span class="line">                    reuseExistingChunk: <span class="literal">true</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>常见配置项目的说明：</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    entry: <span class="string">'./app.js'</span>,</span><br><span class="line">    output: &#123;</span><br><span class="line">        filename: <span class="string">'bundle.js'</span>,</span><br><span class="line">        path: path.resolve(__dirname, <span class="string">'./dist'</span>)</span><br><span class="line">    &#125;,</span><br><span class="line">    optimization: &#123;</span><br><span class="line">         splitChunks: &#123;</span><br><span class="line">            chunks: <span class="string">"all"</span>, <span class="comment">// 表示有3种可能值"initial", "async"和"all"。表示引入模块的方式是同步、异步、全部，默认异步。</span></span><br><span class="line">            minSize: <span class="number">30000</span>, <span class="comment">// 30kb ,默认大于30kb的包大小的时候才进行代码分割</span></span><br><span class="line">            <span class="comment">// maxSize:50000, // 默认没有此配置，可以不配置，有可能会将一个第三方库再次拆分，不建议配置</span></span><br><span class="line">            minChunks: <span class="number">1</span>, <span class="comment">// 表示当一个模块被用了多少次的时候才进行分割，默认1次，就进行分割</span></span><br><span class="line">            maxAsyncRequests: <span class="number">5</span>, <span class="comment">// 同时加载的模块数量，默认是5个。超过5个后，就不会再进行代码分割了（一般不动该配置）</span></span><br><span class="line">            maxInitialRequests: <span class="number">3</span>, <span class="comment">// 入口文件引入的其他模块，默认3个，超过后不再进行代码分割（一般不动该配置）</span></span><br><span class="line">            automaticNameDelimiter: <span class="string">'~'</span>, <span class="comment">// 组和文件名字之间的连接符</span></span><br><span class="line">            name: <span class="literal">true</span>, <span class="comment">// 表示cache里面的名字有效（一般不动该配置）</span></span><br><span class="line">            cacheGroups: &#123;</span><br><span class="line">                vendors: &#123;</span><br><span class="line">                    test: <span class="regexp">/[\\/]node_modules[\\/]/</span>, <span class="comment">// 检测引入库是否在 node_modules 目录下,是的话打包出来默认名为 vandors~bundule.js。</span></span><br><span class="line">                    priority: <span class="number">-10</span>, <span class="comment">// 优先级（比如 -10 大于 default 中的 -20），同时满足两个配置的话，优先走优先级高的配置</span></span><br><span class="line">                    filename: <span class="string">'vendors.js'</span> <span class="comment">// 修改库打包的文件名为 vendors.js</span></span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="keyword">default</span>: &#123;</span><br><span class="line">                    minChunks: <span class="number">2</span>,</span><br><span class="line">                    priority: <span class="number">-20</span>, <span class="comment">// 优先级（比如 -10 大于 default 中的 -20），同时满足两个配置的话，优先走优先级高的配置</span></span><br><span class="line">                    reuseExistingChunk: <span class="literal">true</span> <span class="comment">// 如果一个模块已经被打包过了，再次遇到相同的模块后，直接复用，而不是再次打包</span></span><br><span class="line">                &#125; <span class="comment">// 如果引入的模块不在node_modules里面，走这个属性的配置</span></span><br><span class="line">            &#125;, <span class="comment">// 缓存组，可以将多个库、模块一起进行分析打包到 vendors 或者 default</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>详见官网：<a href="https://www.webpackjs.com/plugins/split-chunks-plugin/#configuration" target="_blank" rel="noopener">https://www.webpackjs.com/plugins/split-chunks-plugin/#configuration</a></p>
<h2 id="动态导入"><a href="#动态导入" class="headerlink" title="动态导入"></a>动态导入</h2><p>对于动态代码拆分时，webpack 提供了两个类似的技术。第一种，也是优先选择的方式是，使用符合 ECMAScript 提案的 <code>import()</code> 语法。第二种，则是使用 <code>webpack</code> 特定的 <code>require.ensure</code>。</p>
<blockquote>
<p>import() 调用会在内部用到 promises。如果在旧有版本浏览器中使用 import()，记得使用 一个 polyfill 库（例如 es6-promise 或 promise-polyfill），来 shim Promise。</p>
</blockquote>
<p>先从配置中移除掉多余的 <code>entry</code> 和 <code>CommonsChunkPlugin</code>：</p>
<p><em>webpack.config.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">  <span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line">- <span class="keyword">const</span> webpack = <span class="built_in">require</span>(<span class="string">'webpack'</span>);</span><br><span class="line">  <span class="keyword">const</span> HTMLWebpackPlugin = <span class="built_in">require</span>(<span class="string">'html-webpack-plugin'</span>);</span><br><span class="line"></span><br><span class="line">  <span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    entry: &#123;</span><br><span class="line">+     index: <span class="string">'./src/index.js'</span></span><br><span class="line">-     index: <span class="string">'./src/index.js'</span>,</span><br><span class="line">-     another: <span class="string">'./src/another-module.js'</span></span><br><span class="line">    &#125;,</span><br><span class="line">    plugins: [</span><br><span class="line">      <span class="keyword">new</span> HTMLWebpackPlugin(&#123;</span><br><span class="line">        title: <span class="string">'Code Splitting'</span></span><br><span class="line">-     &#125;),</span><br><span class="line">+     &#125;)</span><br><span class="line">-     <span class="keyword">new</span> webpack.optimize.CommonsChunkPlugin(&#123;</span><br><span class="line">-       name: <span class="string">'common'</span> <span class="comment">// 指定公共 bundle 的名称。</span></span><br><span class="line">-     &#125;)</span><br><span class="line">    ],</span><br><span class="line">    output: &#123;</span><br><span class="line">      filename: <span class="string">'[name].bundle.js'</span>,</span><br><span class="line">+     chunkFilename: <span class="string">'[name].bundle.js'</span>,</span><br><span class="line">      path: path.resolve(__dirname, <span class="string">'dist'</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;;</span><br></pre></td></tr></table></figure>

<p>注意，这里使用了 <code>chunkFilename</code>，它决定非入口 <code>chunk</code> 的名称。想了解 <code>chunkFilename</code> 更多信息，请查看 <code>output</code> 相关文档。接着，更新我们的项目，移除掉那些现在不会用到的文件:</p>
<p><em>project</em></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">webpack-demo</span><br><span class="line">|- package.json</span><br><span class="line">|- webpack.config.js</span><br><span class="line">|- &#x2F;dist</span><br><span class="line">|- &#x2F;src</span><br><span class="line">  |- index.js</span><br><span class="line">- |- another-module.js</span><br><span class="line">|- &#x2F;node_modules</span><br></pre></td></tr></table></figure>

<p>现在，我们不再使用静态导入 lodash，而是通过使用动态导入来分离一个 chunk：</p>
<p><em>src/index.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">- <span class="keyword">import</span> _ <span class="keyword">from</span> <span class="string">'lodash'</span>;</span><br><span class="line">-</span><br><span class="line">- <span class="function"><span class="keyword">function</span> <span class="title">component</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">+ <span class="function"><span class="keyword">function</span> <span class="title">getComponent</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">-   <span class="keyword">var</span> element = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>);</span><br><span class="line">-</span><br><span class="line">-   <span class="comment">// Lodash, now imported by this script</span></span><br><span class="line">-   element.innerHTML = _.join([<span class="string">'Hello'</span>, <span class="string">'webpack'</span>], <span class="string">' '</span>);</span><br><span class="line">+   <span class="keyword">return</span> <span class="keyword">import</span>(<span class="comment">/* webpackChunkName: "lodash" */</span> <span class="string">'lodash'</span>).then(<span class="function"><span class="params">_</span> =&gt;</span> &#123;</span><br><span class="line">+     <span class="keyword">var</span> element = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>);</span><br><span class="line">+</span><br><span class="line">+     element.innerHTML = _.join([<span class="string">'Hello'</span>, <span class="string">'webpack'</span>], <span class="string">' '</span>);</span><br><span class="line">+</span><br><span class="line">+     <span class="keyword">return</span> element;</span><br><span class="line">+</span><br><span class="line">+   &#125;).catch(<span class="function"><span class="params">error</span> =&gt;</span> <span class="string">'An error occurred while loading the component'</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">- <span class="built_in">document</span>.body.appendChild(component());</span><br><span class="line">+ getComponent().then(<span class="function"><span class="params">component</span> =&gt;</span> &#123;</span><br><span class="line">+   <span class="built_in">document</span>.body.appendChild(component);</span><br><span class="line">+ &#125;)</span><br></pre></td></tr></table></figure>

<p>注意，在注释中使用了 webpackChunkName。这样做会导致我们的 bundle 被命名为 lodash.bundle.js ，而不是 [id].bundle.js 。想了解更多关于 webpackChunkName 和其他可用选项，请查看 import() 相关文档。让我们执行 webpack，查看 lodash 是否会分离到一个单独的 bundle：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Hash: a27e5bf1dd73c675d5c9</span><br><span class="line">Version: webpack 2.6.1</span><br><span class="line">Time: 544ms</span><br><span class="line">           Asset     Size  Chunks                    Chunk Names</span><br><span class="line">lodash.bundle.js   541 kB       0  [emitted]  [big]  lodash</span><br><span class="line"> index.bundle.js  6.35 kB       1  [emitted]         index</span><br><span class="line">   [0] .&#x2F;~&#x2F;lodash&#x2F;lodash.js 540 kB &#123;0&#125; [built]</span><br><span class="line">   [1] .&#x2F;src&#x2F;index.js 377 bytes &#123;1&#125; [built]</span><br><span class="line">   [2] (webpack)&#x2F;buildin&#x2F;global.js 509 bytes &#123;0&#125; [built]</span><br><span class="line">   [3] (webpack)&#x2F;buildin&#x2F;module.js 517 bytes &#123;0&#125; [built]</span><br><span class="line">由于 import() 会返回一个 promise，因此它可以和 async 函数一起使用。但是，需要使用像 Babel 这样的预处理器和Syntax Dynamic Import Babel Plugin。下面是如何通过 async 函数简化代码：</span><br></pre></td></tr></table></figure>

<p><em>src/index.js</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">- <span class="function"><span class="keyword">function</span> <span class="title">getComponent</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">+ <span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">getComponent</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">-   <span class="keyword">return</span> <span class="keyword">import</span>(<span class="comment">/* webpackChunkName: "lodash" */</span> <span class="string">'lodash'</span>).then(<span class="function"><span class="params">_</span> =&gt;</span> &#123;</span><br><span class="line">-     <span class="keyword">var</span> element = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>);</span><br><span class="line">-</span><br><span class="line">-     element.innerHTML = _.join([<span class="string">'Hello'</span>, <span class="string">'webpack'</span>], <span class="string">' '</span>);</span><br><span class="line">-</span><br><span class="line">-     <span class="keyword">return</span> element;</span><br><span class="line">-</span><br><span class="line">-   &#125;).catch(<span class="function"><span class="params">error</span> =&gt;</span> <span class="string">'An error occurred while loading the component'</span>);</span><br><span class="line">+   <span class="keyword">var</span> element = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>);</span><br><span class="line">+   <span class="keyword">const</span> _ = <span class="keyword">await</span> <span class="keyword">import</span>(<span class="comment">/* webpackChunkName: "lodash" */</span> <span class="string">'lodash'</span>);</span><br><span class="line">+</span><br><span class="line">+   element.innerHTML = _.join([<span class="string">'Hello'</span>, <span class="string">'webpack'</span>], <span class="string">' '</span>);</span><br><span class="line">+</span><br><span class="line">+   <span class="keyword">return</span> element;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  getComponent().then(<span class="function"><span class="params">component</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">document</span>.body.appendChild(component);</span><br><span class="line">  &#125;);</span><br></pre></td></tr></table></figure>

<hr>
<h1 id="懒加载"><a href="#懒加载" class="headerlink" title="懒加载"></a>懒加载</h1><p>懒加载或者按需加载，是一种很好的优化网页或应用的方式。这种方式实际上是先把你的代码在一些逻辑断点处分离开，然后在一些代码块中完成某些操作后，立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度，减轻了它的总体体积，因为某些代码块可能永远不会被加载。</p>
<p>比如一些框架的路由配置，就用到了懒加载技术，点击不同的页面，懒加载不同的打包代码。</p>
<p><em>text.js 数据文件</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> () =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> [<span class="string">'白'</span>, <span class="string">'日'</span>, <span class="string">'依'</span>, <span class="string">'山'</span>, <span class="string">'尽'</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><em>a.js 业务代码</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> _ <span class="keyword">from</span> <span class="string">'loadsh'</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">component</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> button = <span class="built_in">document</span>.createElement(<span class="string">'button'</span>);</span><br><span class="line">    button.innerText = <span class="string">'生成'</span>;</span><br><span class="line">    <span class="built_in">document</span>.getElementById(<span class="string">'root'</span>).appendChild(button);</span><br><span class="line">    <span class="keyword">let</span> div = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>);</span><br><span class="line"></span><br><span class="line">    button.addEventListener(<span class="string">'click'</span>, () =&gt; &#123;</span><br><span class="line">        <span class="keyword">import</span>(<span class="comment">/* webpackChunkName:"text" */</span> <span class="string">'./text'</span>).then(<span class="function"><span class="params">module</span> =&gt;</span> &#123;</span><br><span class="line">            div.innerText = _.join(<span class="built_in">module</span>.default(), <span class="string">'~'</span>);</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="keyword">return</span> div;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.getElementById(<span class="string">'root'</span>).appendChild(component());</span><br></pre></td></tr></table></figure>

<p><em>app.js 入口文件</em></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="string">'./a'</span>;</span><br></pre></td></tr></table></figure>

<p>页面初始化，并不会加载 text 部分的打包代码，而是在点击按钮后，才去加载这个打包的代码。</p>
<hr>
<h1 id="打包分析-analyse"><a href="#打包分析-analyse" class="headerlink" title="打包分析 analyse"></a>打包分析 analyse</h1><p>在 webpack 项目下生成打包文件状态文件 <code>stats.json</code>，在官方网站上进行包的分析。</p>
<p>官方分析网站：<a href="http://webpack.github.io/analyse/" target="_blank" rel="noopener">http://webpack.github.io/analyse/</a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">webpack --profile --json &gt; stats.json</span><br></pre></td></tr></table></figure>

<p>直接运行这个命令是不行的，需要在 <code>package.json</code> 进行配置。</p>
<p><em>package.json</em></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"name"</span>: <span class="string">"demo8"</span>,</span><br><span class="line">  <span class="attr">"version"</span>: <span class="string">"1.0.0"</span>,</span><br><span class="line">  <span class="attr">"description"</span>: <span class="string">"## lazyloading"</span>,</span><br><span class="line">  <span class="attr">"main"</span>: <span class="string">"app.js"</span>,</span><br><span class="line">  <span class="attr">"dependencies"</span>: &#123;</span><br><span class="line">    <span class="attr">"loadsh"</span>: <span class="string">"0.0.4"</span>,</span><br><span class="line">    <span class="attr">"webpack"</span>: <span class="string">"^4.43.0"</span>,</span><br><span class="line">    <span class="attr">"webpack-cli"</span>: <span class="string">"^3.3.12"</span>,</span><br><span class="line">    <span class="attr">"webpack-dev-server"</span>: <span class="string">"^3.11.0"</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">"devDependencies"</span>: &#123;</span><br><span class="line">    <span class="attr">"clean-webpack-plugin"</span>: <span class="string">"^3.0.0"</span>,</span><br><span class="line">    <span class="attr">"html-webpack-plugin"</span>: <span class="string">"^4.3.0"</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">"scripts"</span>: &#123;</span><br><span class="line">    <span class="attr">"build"</span>: <span class="string">"webpack"</span>,</span><br><span class="line">    <span class="attr">"stats"</span>: <span class="string">"webpack --profile --json &gt; stats.json"</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">"author"</span>: <span class="string">""</span>,</span><br><span class="line">  <span class="attr">"license"</span>: <span class="string">"ISC"</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如上配置，可以运行 <code>npm run stats</code> 来生成 <code>stats.json</code> 文件。</p>
<p>或者不配置的话，直接运行 <code>npx webpack --profile --json &gt; stats.json</code> ，也可生成 <code>stats.json</code>。</p>
<p>通过官方分析工具的引导，上传 <code>stats.json</code> 文件，生成分析图表。</p>
<p><img src="https://inews.gtimg.com/newsapp_ls/0/12134390255/0" alt="图示"></p>
<p>官方分析工具 是一个好的初始选择。下面是一些社区支持(community-supported)的可选工具：</p>
<ul>
<li>webpack-chart: webpack 数据交互饼图。</li>
<li>webpack-visualizer: 可视化并分析你的 bundle，检查哪些模块占用空间，哪些可能是重复使用的。</li>
<li>webpack-bundle-analyzer: 一款分析 bundle 内容的插件及 CLI 工具，以便捷的、交互式、可缩放的树状图形式展现给用户。</li>
</ul>
<p>详情：<a href="https://www.webpackjs.com/guides/code-splitting/#bundle-%E5%88%86%E6%9E%90-bundle-analysis-" target="_blank" rel="noopener">https://www.webpackjs.com/guides/code-splitting/#bundle-%E5%88%86%E6%9E%90-bundle-analysis-</a></p>
<hr>
<h1 id="预抓取-prefetching-预加载-preloading-模块"><a href="#预抓取-prefetching-预加载-preloading-模块" class="headerlink" title="预抓取(prefetching)/预加载(preloading)模块"></a>预抓取(prefetching)/预加载(preloading)模块</h1><p>webpack 4.6.0+ 增加了对 <code>prefetching</code> 和 <code>preloading</code> 的支持。</p>
<ul>
<li><code>prefetching</code>：在浏览器将来某个事件点触发执行资源。</li>
<li><code>preloading</code>：在浏览器带宽宽裕时进行加载资源。</li>
</ul>
<p>通常打包优化的思路是做缓存，将同步或异步的模块，进行拆分成多个模块，然后利用浏览器缓存机制。第一次加载，后期缓存，来提升性能。</p>
<p>但是缓存对页面性能的提升有限，webpack 的设计思想是异步加载的思路。这也就是为什么 <code>splictChunks</code> 的配置项，默认为 <code>async</code> (异步)的原因。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line">  optimization: &#123;</span><br><span class="line">         splitChunks: &#123;</span><br><span class="line">            chunks: <span class="string">"async"</span>, </span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>

<h2 id="prefetching"><a href="#prefetching" class="headerlink" title="prefetching"></a>prefetching</h2><hr>
<h1 id="css-文件的代码分割"><a href="#css-文件的代码分割" class="headerlink" title="css 文件的代码分割"></a>css 文件的代码分割</h1><hr>
<h1 id="webpack-与浏览器缓存"><a href="#webpack-与浏览器缓存" class="headerlink" title="webpack 与浏览器缓存"></a>webpack 与浏览器缓存</h1><hr>
<h1 id="Shimming-的作用"><a href="#Shimming-的作用" class="headerlink" title="Shimming 的作用"></a>Shimming 的作用</h1>
      </div>
      
      
      
    </div>
    

    
    
    


          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#基本概念"><span class="nav-number">1.</span> <span class="nav-text">基本概念</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#入口-entry"><span class="nav-number">1.1.</span> <span class="nav-text">入口(entry)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#出口-output"><span class="nav-number">1.2.</span> <span class="nav-text">出口(output)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#loader"><span class="nav-number">1.3.</span> <span class="nav-text">loader</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#插件-plugins"><span class="nav-number">1.4.</span> <span class="nav-text">插件(plugins)</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#安装"><span class="nav-number">2.</span> <span class="nav-text">安装</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#本地安装"><span class="nav-number">2.1.</span> <span class="nav-text">本地安装</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#全局安装"><span class="nav-number">2.2.</span> <span class="nav-text">全局安装</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#webpack-config-js"><span class="nav-number">3.</span> <span class="nav-text">webpack.config.js</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#loader-1"><span class="nav-number">4.</span> <span class="nav-text">loader</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#文件"><span class="nav-number">4.1.</span> <span class="nav-text">文件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#JSON"><span class="nav-number">4.2.</span> <span class="nav-text">JSON</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#转换编译-Transpiling"><span class="nav-number">4.3.</span> <span class="nav-text">转换编译(Transpiling)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#模板-Templating"><span class="nav-number">4.4.</span> <span class="nav-text">模板(Templating)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#样式"><span class="nav-number">4.5.</span> <span class="nav-text">样式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#清理和测试-Linting-amp-amp-Testing"><span class="nav-number">4.6.</span> <span class="nav-text">清理和测试(Linting &amp;&amp; Testing)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#框架-Frameworks"><span class="nav-number">4.7.</span> <span class="nav-text">框架(Frameworks)</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#loader-用法"><span class="nav-number">5.</span> <span class="nav-text">loader 用法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#加载-CSS"><span class="nav-number">5.1.</span> <span class="nav-text">加载 CSS</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#安装-1"><span class="nav-number">5.1.1.</span> <span class="nav-text">安装</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#用法"><span class="nav-number">5.1.2.</span> <span class="nav-text">用法</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#加载图片"><span class="nav-number">5.2.</span> <span class="nav-text">加载图片</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#安装-2"><span class="nav-number">5.2.1.</span> <span class="nav-text">安装</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#用法-1"><span class="nav-number">5.2.2.</span> <span class="nav-text">用法</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#加载字体"><span class="nav-number">5.3.</span> <span class="nav-text">加载字体</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#用法-2"><span class="nav-number">5.3.1.</span> <span class="nav-text">用法</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#处理-sass-scss-样式文件"><span class="nav-number">5.4.</span> <span class="nav-text">处理 sass&#x2F;scss 样式文件</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#安装-3"><span class="nav-number">5.4.1.</span> <span class="nav-text">安装</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#用法-3"><span class="nav-number">5.4.2.</span> <span class="nav-text">用法</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#处理-css3-兼容前缀"><span class="nav-number">5.5.</span> <span class="nav-text">处理 css3 兼容前缀</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#安装-4"><span class="nav-number">5.5.1.</span> <span class="nav-text">安装</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#配置"><span class="nav-number">5.5.2.</span> <span class="nav-text">配置</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Babel"><span class="nav-number">6.</span> <span class="nav-text">Babel</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#安装-5"><span class="nav-number">6.1.</span> <span class="nav-text">安装</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#配置-1"><span class="nav-number">6.2.</span> <span class="nav-text">配置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#创建-babelrc-配置文件"><span class="nav-number">6.3.</span> <span class="nav-text">创建 .babelrc 配置文件</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#插件用法"><span class="nav-number">7.</span> <span class="nav-text">插件用法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#html-webpack-plugin"><span class="nav-number">7.1.</span> <span class="nav-text">html-webpack-plugin</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#安装-6"><span class="nav-number">7.1.1.</span> <span class="nav-text">安装</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#用法-4"><span class="nav-number">7.1.2.</span> <span class="nav-text">用法</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#clean-webpack-plugin"><span class="nav-number">7.2.</span> <span class="nav-text">clean-webpack-plugin</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#安装-7"><span class="nav-number">7.2.1.</span> <span class="nav-text">安装</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#使用"><span class="nav-number">7.2.2.</span> <span class="nav-text">使用</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#多入口打包配置"><span class="nav-number">8.</span> <span class="nav-text">多入口打包配置</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#source-map"><span class="nav-number">9.</span> <span class="nav-text">source map</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#webpack-dev-server"><span class="nav-number">10.</span> <span class="nav-text">webpack-dev-server</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#安装-8"><span class="nav-number">10.1.</span> <span class="nav-text">安装</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#配置-2"><span class="nav-number">10.2.</span> <span class="nav-text">配置</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#模块热替换（HMR）"><span class="nav-number">11.</span> <span class="nav-text">模块热替换（HMR）</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#tree-shaking"><span class="nav-number">12.</span> <span class="nav-text">tree shaking</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#将文件标记为无副作用-side-effect-free"><span class="nav-number">12.1.</span> <span class="nav-text">将文件标记为无副作用(side-effect-free)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#压缩输出"><span class="nav-number">12.2.</span> <span class="nav-text">压缩输出</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#生产环境构建"><span class="nav-number">13.</span> <span class="nav-text">生产环境构建</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#webpack-merge"><span class="nav-number">13.1.</span> <span class="nav-text">webpack-merge</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#安装-9"><span class="nav-number">13.1.1.</span> <span class="nav-text">安装</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#配置使用"><span class="nav-number">13.1.2.</span> <span class="nav-text">配置使用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#NPM-Scripts"><span class="nav-number">13.2.</span> <span class="nav-text">NPM Scripts</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#代码分离"><span class="nav-number">14.</span> <span class="nav-text">代码分离</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#入口起点（配置-entry）"><span class="nav-number">14.1.</span> <span class="nav-text">入口起点（配置 entry）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#防止重复（使用-CommonsChunkPlugin）"><span class="nav-number">14.2.</span> <span class="nav-text">防止重复（使用 CommonsChunkPlugin）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#SplitChunksPlugin"><span class="nav-number">14.3.</span> <span class="nav-text">SplitChunksPlugin</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#动态导入"><span class="nav-number">14.4.</span> <span class="nav-text">动态导入</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#懒加载"><span class="nav-number">15.</span> <span class="nav-text">懒加载</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#打包分析-analyse"><span class="nav-number">16.</span> <span class="nav-text">打包分析 analyse</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#预抓取-prefetching-预加载-preloading-模块"><span class="nav-number">17.</span> <span class="nav-text">预抓取(prefetching)&#x2F;预加载(preloading)模块</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#prefetching"><span class="nav-number">17.1.</span> <span class="nav-text">prefetching</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#css-文件的代码分割"><span class="nav-number">18.</span> <span class="nav-text">css 文件的代码分割</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#webpack-与浏览器缓存"><span class="nav-number">19.</span> <span class="nav-text">webpack 与浏览器缓存</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Shimming-的作用"><span class="nav-number">20.</span> <span class="nav-text">Shimming 的作用</span></a></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Albert Guo"
      src="https://inews.gtimg.com/newsapp_ls/0/12122532695/0">
  <p class="site-author-name" itemprop="name">Albert Guo</p>
  <div class="site-description" itemprop="description">郭鹏松的个人博客</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives">
          <span class="site-state-item-count">19</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">6</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="mailto:albert-guo@outlook.com" title="E-Mail → mailto:albert-guo@outlook.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Albert Guo</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

</body>
</html>
